//: [Previous](@previous)
import Foundation
//: ## 方法(Method)
/**
 枚举 / 结构体 / 类 都可以定义实例方法 / 类型方法
  - 实例方法(Instance Method) : 通过实例调用
  - 类型方法(type Method) : 通过类型调用, 用 static 或者 class 关键字定义
 
 self
 在实例方法中代表实例
 在类型方法中代表类型
 */
class Car {
    static var count = 0
    
    init() {
        Car.count += 1
    }
    static func getCount() -> Int {
        count
    }
}
let C1 = Car()
let C2 = Car()
let C3 = Car()
print(Car.getCount()) // 3
// 在类方法static func getCount()中, count 等价于  self.count / Car.self.count / Car.count
//: ## mutating
/**
 结构体 和 枚举 都是值类型, 默认情况下, 值类型的属性不能被自身的实例方法修改(其实就是不允许实例方法修改实例属性的内存, 值类型的值是直接存在属性的内存里面, 值变了,  其实内存也相当于变了)
 但是在func关键字前面加上 mutating, 可以允许这种修改行为
 */
struct point {
    var num = 0
//    func add(numB : Int){
//        num += numB
//    }// 这样子写会报错, num是值类型, 不能被自身的实例方法直接修改了,
    mutating func add(numB : Int){
        num += numB
    }
}
//举例一个需求:有低,中,高3个按钮, 点其中一个, 另外一个点亮
enum StateSwitch {
    case low, middle, high
    mutating func next() {
        switch self {
        case .low:
            self = .middle
        case .middle:
            self = .high
        case .high:
            self = .low
        }
    }
}
//: ## @discardableResult
//在func前面加上 @discardableResult, 可以消除因函数调用后返回值没有被使用的警告⚠️
struct point1 {
    var x = 1
    var y = 2
    @discardableResult mutating func add(addNum: Int) -> Int {
        x += addNum //这里因为同值对象的属性在func里面被修改了值, 所以需要加上mutating
        return x
    }
}
var p = point1()
p.add(addNum: 10)

@discardableResult
func get() -> Int {
    return 10
}
get()

//: ## 将方法赋值给var/let
/*
 方法也可以像函数那样, 赋值给一个let或者var
 
 */
struct Person2 {
    var age: Int
    func run(_ v: Int) {
        print("func run",age,v)
    }
    static func run(_ v: Int){//类型方法
        print("static func run",v)
    }
}
let fn1 = Person2.run //直接把类型方法赋值给fn1
fn1(20) //fn1此时的类型(int)->() 输出:static func run 20

let fn2: (Int)->() = Person2.run //也可以直接规定好类型
fn2(30) //fn1此时的类型(int)->() 输出:static func run 30

let fn3: (Person2) -> ((Int)->()) = Person2.run
fn3(Person2(age: 40))(30) //输出:func run 40 30



















//: [Next](@next)
